#define GPACON		*((volatile unsigned long *)0x7F008000)

#define ULCON0 		*((volatile unsigned long *)0x7F005000)
#define UCON0 		*((volatile unsigned long *)0x7F005004)
#define UFCON0 		*((volatile unsigned long *)0x7F005008)
#define UMCON0		*((volatile unsigned long *)0x7F00500C)
#define UTRSTAT0 	*((volatile unsigned long *)0x7F005010)
#define UFSTAT0 	*((volatile unsigned long *)0x7F005018)
#define UTXH0  		*((volatile unsigned char *)0x7F005020)
#define URXH0 		*((volatile unsigned char *)0x7F005024)
#define UBRDIV0 	*((volatile unsigned short *)0x7F005028)
#define UDIVSLOT0	*((volatile unsigned short *)0x7F00502C)

/* UART0初始化 */
void uart_init(void)
{
	/*
	** 配置GPA_0为UART_0_RXD
	** 配置GPA_1为UART_0_TXD
	*/
	GPACON &= ~0xFF;	//最好只向寄存器写一次 GPACON = (GPACON & ~0xFF) | 0x22;
	GPACON |= 0x22;

	/* 8-bits/One stop bit/No parity/Normal mode operation */
	ULCON0 = 0x03 | (0x00 << 2) | (0x00 << 3) | (0x00 << 6);

	/* Interrupt request or polling mode/Normal transmit/Normal operation/PCLK/ */
	UCON0 = 0x01 | (0x01 << 2) | (0x02 << 10);

	/* FIFO Enable*/
	UFCON0 = 0x01;
	
	UMCON0 = 0x00;	//流量控制

	/*
	** 波特率计算：115200bps
	** PCLK = 66.5MHz
	** DIV_VAL = (66500000/(115200 x 16))-1 = 36.08 - 1 = 35.08
	** UBRDIV0 = 35(DIV_VAL的整数部分)
	** (num of 1's in UDIVSLOTn)/16 = 0.08
	** (num of 1's in UDIVSLOTn) = 1
	** UDIVSLOT0 = 0x0080 (查表)
	*/
	UBRDIV0 = 35;
	UDIVSLOT0 = 0x0080;
}

static void uart_send_byte(const char byte)		/* static 限制函数仅能在文件内部使用 */
{
	while(UFSTAT0 & (1<<14));	/* 如果发送缓冲区满，则等待发送 */
	//while (!(UTRSTAT0 & (1 << 2)));	/* 等待发送缓冲区为空 */
	UTXH0 = byte;					/* 发送一字节数据 */		
}

static char uart_recv_byte(void)
{
	while((UFSTAT0 & 0x7f) == 0);	//缓冲区没有数据，等待接收数据
	//while (!(UTRSTAT0 & 1));		/* 等待接收缓冲区有数据可读 */
	return URXH0;					/* 接收一字节数据 */		
}

void putchar(const char c)
{
	uart_send_byte(c);
	/* 如果只写'\n'，只是换行，而不会跳到下一行开头 */
	if (c == '\n')
		uart_send_byte('\r');
}

char getchar(void)
{
	char c;
	c = uart_recv_byte();
	return c;
}

void puts(const char *str)
{
	char *p = (char *)str;
	while (*p)
		putchar(*p++);
	putchar('\n');
}

